package com.collabscm.pf.web;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.collabscm.pf.logging.Logger;
import com.collabscm.pf.logging.LoggerFactory;
import com.collabscm.pf.util.ReflectionUtils;
import com.collabscm.pf.vo.ConditionMarchType;
import com.collabscm.pf.vo.QueryCondition;
import com.collabscm.pf.vo.QueryFilter;
import com.collabscm.pf.vo.QueryParameters;

/**
 * 查询参数构建器，用于根据QueryCondition创建出实际的QueryParameters对象。
 *
 * @author Zeng Raoxing
 */
public class QueryParametersBuilder {
	private static class BuilderHolder {
		private static QueryParametersBuilder holder = new QueryParametersBuilder();
	}
	/**
	 * 得到QueryParametersBuilder的实例
	 */
	public static QueryParametersBuilder getInstance() {
		return BuilderHolder.holder;
	}
	private QueryParametersBuilder() {}
	private Logger logger = LoggerFactory.getLogger(QueryParametersBuilder.class);
	/**
	 * QueryCondition对应的解析类的Map对象
	 */
	private Map<Class<? extends QueryCondition>, List<PropertyFilter>> breakdownMap 
				= new HashMap<Class<? extends QueryCondition>, List<PropertyFilter>>();
	
	public QueryParameters build(QueryCondition qc) {
		QueryParameters parameters = new QueryParameters();
		List<PropertyFilter> filterList = getFilterList(qc.getClass());
		//添加过滤条件
		for(PropertyFilter filter: filterList) {
			Object condition = ReflectionUtils.invokeMethod(filter.getter, qc);
			if(condition != null) {
				if(ConditionMarchType.LIKE.equals(filter.marchType)) {
					parameters.addFilter(filter.parameterName, "%" + condition + "%");//如果是like，那么自动在前后添加上%
				} else {
					parameters.addFilter(filter.parameterName, condition);
				}
			}
		}
		//添加排序
		if(qc.getOrderBy() != null) {
			parameters.setOrder(qc.getOrderBy(), qc.isAscending());
		}
		//设置本次应取的数据范围
		if(qc.getPageNumber() != null) {
			parameters.setStart((qc.getPageNumber() - 1)*qc.getPageSize());
			parameters.setSize(qc.getPageSize());
		}
		return parameters;
	}
	
	/**
	 * 得到某个类对性的过滤条件列表，如果没有就自动初始化。
	 * @param clazz
	 * @return
	 */
	private List<PropertyFilter> getFilterList(Class<? extends QueryCondition> clazz) {
		List<PropertyFilter> filterList = breakdownMap.get(clazz);
		if(filterList == null) {
			filterList = new ArrayList<PropertyFilter>();
			breakdownMap.put(clazz, filterList);
			fillFilterList(clazz, filterList);
			if(filterList.isEmpty()) {
				logger.error("类{}没有定义任何的@QueryFilter，将无法自动匹配。", clazz);
			}
		}
		return filterList;
	}
	
	/**
	 * 填充过滤信息列表
	 * @param clazz
	 * @param filterList
	 */
	private void fillFilterList(Class<? extends QueryCondition> clazz, List<PropertyFilter> filterList) {
		for(Field field: clazz.getFields()) {
			QueryFilter filter = field.getAnnotation(QueryFilter.class);
			if(filter != null) {
				PropertyFilter pf = new PropertyFilter();
				String fieldName = field.getName();
				if(filter.parameterName().equals("")) {//如果为定义特殊的参数名称，那么就是以变量名作为参数名
					pf.parameterName = fieldName;
				} else {
					pf.parameterName = filter.parameterName();
				}
				pf.marchType = filter.marchType();
				pf.getter = ReflectionUtils.getGetterMethod(clazz, fieldName);
				filterList.add(pf);
			}
		}
	}
		
	/**
	 * 属性过滤
	 *
	 * @author Zeng Raoxing
	 */
	private static class PropertyFilter {
		private String parameterName;
		private ConditionMarchType marchType;
		private Method getter;//属性对应的get方法。
	}

}
